package dao

import (
	"database/sql"
	"fmt"
	"gitee.com/youbeiwuhuan/gin-practice/go-gorm2/dao/model"
	"gitee.com/youbeiwuhuan/gin-practice/go-gorm2/dao/plugin"
	"gitee.com/youbeiwuhuan/gin-practice/go-gorm2/utils/sqls"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
	"gorm.io/gorm/schema"
	"time"
)

var db *gorm.DB = init0()

func init0() *gorm.DB {
	dsn := "root:fan1988@tcp(127.0.0.1:3306)/sa_token?charset=utf8mb4&parseTime=True&loc=Local"
	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
		Logger: logger.Default.LogMode(logger.Info), //配置日志级别，打印出所有的sql
		NamingStrategy: schema.NamingStrategy{
			TablePrefix: "t_", // 表名前缀，`User` 的表名应该是 `t_users`
		},
	})
	if err != nil {
		fmt.Println("open mysql failed,", err)
		panic(err)
	}

	// 注册插件
	db.Use(plugin.NewMyCustomPlugin())
	//db.Use(crypto.NewCryptoPlugin())

	sqlDB, _ := db.DB()
	sqlDB.SetMaxIdleConns(10)
	sqlDB.SetMaxOpenConns(500)
	sqlDB.SetConnMaxLifetime(time.Hour)

	return db
}

func GetById() {
	u := &model.User{}
	// 根据主键获取记录（仅适用于整型主键）
	db.First(u, 1)
	// SELECT * FROM users WHERE id = 23;
	fmt.Println("", u)

	// 根据主键获取记录，如果是非整型主键
	//db.First(&u, "id = ?", "string_primary_key")
	// SELECT * FROM users WHERE id = 'string_primary_key';
}

func GetByColumn() {
	users := []model.User{}
	db.Find(&users, model.User{UserName: "admin"})
	// SELECT * FROM users WHERE user_name = 'admin';
	fmt.Println("", users)
}

func UpdateById() int64 {
	u := model.User{
		Id:       34,
		UserName: "admin22",
	}

	// the user of `Model(&user)` needs to have primary key value, it is `111` in this example
	tx := db.Model(&u).Updates(u)

	return tx.RowsAffected
}

func DeleteById() int64 {

	u := model.User{Id: 34}
	/// 删除一条已有的记录（email 的主键值为 10）
	tx := db.Delete(&u)
	// DELETE from emails where id=10;

	return tx.RowsAffected
}

func first() {
	u := &model.User{}
	db.First(u)
	fmt.Println("", u)
}

func rawSql() {
	sql := "select * from sys_user where id = ?"
	u := &model.User{}
	db.Raw(sql, 1).Scan(u)
	//db.Raw(sql, 1).Row()
	fmt.Printf("affected rows: %d\n", db.RowsAffected)
	fmt.Println(db.Error)
	fmt.Println(u)
}

func execSql() {
	sql := "select * from sys_user where id = ?"
	u := &model.User{}
	//db.Exec(sql, 1).Scan(u)
	row := db.Exec(sql, 1).Row()
	row.Scan(u)
	fmt.Printf("affected rows: %d\n", db.RowsAffected)
	fmt.Println(db.Error)
	fmt.Println(u)
}

func trasaction() {

	db.Transaction(func(tx *gorm.DB) error {

		defer func(tx *gorm.DB) {
			if err := recover(); err != nil {
				tx.Rollback()
			} else {
				fmt.Println("没有panic的异常")
			}
		}(tx)

		u := &model.User{
			Id: 34,
		}
		tx.Save(u)

		//tx.Commit()

		// 返回 nil 则提交 事务，返回 具体error 回滚事务
		return nil
	})

}

func trasaction2(dbOpers func(tx *gorm.DB) error) {

	db.Transaction(func(tx *gorm.DB) error {

		defer func(tx *gorm.DB) {
			if err := recover(); err != nil {
				tx.Rollback()
			} else {
				fmt.Println("没有panic的异常")
			}
		}(tx)

		return dbOpers(tx)

	})

}

func page() {
	sql := "select * from sys_user where id = ?"
	var users []model.User
	page := 1
	pageSize := 10
	db.Raw(sql, 1).Offset((page - 1) * pageSize).Limit(pageSize).Scan(&users)
	fmt.Printf("affected rows: %d\n", db.RowsAffected)
	fmt.Println(db.Error)
	fmt.Println(users)
}

func namedParam1() {
	sql0 := "select * from sys_user where id = @id"
	u := &model.User{}
	//db.Exec(sql, 1).Scan(u)
	row := db.Exec(sql0, sql.Named("id", 1)).Row()
	row.Scan(u)
	fmt.Printf("affected rows: %d\n", db.RowsAffected)
	fmt.Println(db.Error)
	fmt.Println(u)
}

func namedParam2() {
	sql0 := "select * from sys_user where id = @Id"
	u := &model.User{}
	p := model.User{
		Id: 1,
	}
	row := db.Exec(sql0, sqls.ToNamedArgs(p)).Row()
	row.Scan(u)
	fmt.Printf("affected rows: %d\n", db.RowsAffected)
	fmt.Println(db.Error)
	fmt.Println(u)
}
